1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.common.testing;
18
19 import static com.google.common.base.Preconditions.checkArgument;
20
21 import com.google.common.annotations.Beta;
22 import com.google.common.base.CharMatcher;
23 import com.google.common.base.Charsets;
24 import com.google.common.base.Defaults;
25 import com.google.common.base.Equivalence;
26 import com.google.common.base.Joiner;
27 import com.google.common.base.Optional;
28 import com.google.common.base.Predicate;
29 import com.google.common.base.Predicates;
30 import com.google.common.base.Splitter;
31 import com.google.common.base.Stopwatch;
32 import com.google.common.base.Ticker;
33 import com.google.common.collect.BiMap;
34 import com.google.common.collect.ClassToInstanceMap;
35 import com.google.common.collect.ImmutableBiMap;
36 import com.google.common.collect.ImmutableClassToInstanceMap;
37 import com.google.common.collect.ImmutableCollection;
38 import com.google.common.collect.ImmutableList;
39 import com.google.common.collect.ImmutableListMultimap;
40 import com.google.common.collect.ImmutableMap;
41 import com.google.common.collect.ImmutableMultimap;
42 import com.google.common.collect.ImmutableMultiset;
43 import com.google.common.collect.ImmutableSet;
44 import com.google.common.collect.ImmutableSetMultimap;
45 import com.google.common.collect.ImmutableSortedMap;
46 import com.google.common.collect.ImmutableSortedMultiset;
47 import com.google.common.collect.ImmutableSortedSet;
48 import com.google.common.collect.ImmutableTable;
49 import com.google.common.collect.Iterators;
50 import com.google.common.collect.ListMultimap;
51 import com.google.common.collect.MapConstraint;
52 import com.google.common.collect.MapConstraints;
53 import com.google.common.collect.MapDifference;
54 import com.google.common.collect.Maps;
55 import com.google.common.collect.Multimap;
56 import com.google.common.collect.Multimaps;
57 import com.google.common.collect.Multiset;
58 import com.google.common.collect.Ordering;
59 import com.google.common.collect.PeekingIterator;
60 import com.google.common.collect.Range;
61 import com.google.common.collect.RowSortedTable;
62 import com.google.common.collect.SetMultimap;
63 import com.google.common.collect.Sets;
64 import com.google.common.collect.SortedMapDifference;
65 import com.google.common.collect.SortedMultiset;
66 import com.google.common.collect.SortedSetMultimap;
67 import com.google.common.collect.Table;
68 import com.google.common.collect.Tables;
69 import com.google.common.collect.TreeBasedTable;
70 import com.google.common.collect.TreeMultimap;
71 import com.google.common.io.ByteSink;
72 import com.google.common.io.ByteSource;
73 import com.google.common.io.ByteStreams;
74 import com.google.common.io.CharSink;
75 import com.google.common.io.CharSource;
76 import com.google.common.primitives.Primitives;
77 import com.google.common.primitives.UnsignedInteger;
78 import com.google.common.primitives.UnsignedLong;
79
80 import java.io.ByteArrayInputStream;
81 import java.io.ByteArrayOutputStream;
82 import java.io.File;
83 import java.io.InputStream;
84 import java.io.OutputStream;
85 import java.io.PrintStream;
86 import java.io.PrintWriter;
87 import java.io.Reader;
88 import java.io.Serializable;
89 import java.io.StringReader;
90 import java.io.StringWriter;
91 import java.io.Writer;
92 import java.lang.reflect.AnnotatedElement;
93 import java.lang.reflect.Array;
94 import java.lang.reflect.Constructor;
95 import java.lang.reflect.Field;
96 import java.lang.reflect.GenericDeclaration;
97 import java.lang.reflect.InvocationTargetException;
98 import java.lang.reflect.Modifier;
99 import java.lang.reflect.Type;
100 import java.math.BigDecimal;
101 import java.math.BigInteger;
102 import java.nio.Buffer;
103 import java.nio.ByteBuffer;
104 import java.nio.CharBuffer;
105 import java.nio.DoubleBuffer;
106 import java.nio.FloatBuffer;
107 import java.nio.IntBuffer;
108 import java.nio.LongBuffer;
109 import java.nio.ShortBuffer;
110 import java.nio.charset.Charset;
111 import java.util.ArrayDeque;
112 import java.util.Arrays;
113 import java.util.Collection;
114 import java.util.Comparator;
115 import java.util.Currency;
116 import java.util.Deque;
117 import java.util.Iterator;
118 import java.util.List;
119 import java.util.ListIterator;
120 import java.util.Locale;
121 import java.util.Map;
122 import java.util.NavigableMap;
123 import java.util.NavigableSet;
124 import java.util.Queue;
125 import java.util.Random;
126 import java.util.Set;
127 import java.util.SortedMap;
128 import java.util.SortedSet;
129 import java.util.concurrent.BlockingDeque;
130 import java.util.concurrent.BlockingQueue;
131 import java.util.concurrent.ConcurrentHashMap;
132 import java.util.concurrent.ConcurrentMap;
133 import java.util.concurrent.ConcurrentNavigableMap;
134 import java.util.concurrent.ConcurrentSkipListMap;
135 import java.util.concurrent.CountDownLatch;
136 import java.util.concurrent.Executor;
137 import java.util.concurrent.LinkedBlockingDeque;
138 import java.util.concurrent.ScheduledThreadPoolExecutor;
139 import java.util.concurrent.ThreadFactory;
140 import java.util.concurrent.ThreadPoolExecutor;
141 import java.util.concurrent.TimeUnit;
142 import java.util.logging.Level;
143 import java.util.logging.Logger;
144 import java.util.regex.MatchResult;
145 import java.util.regex.Matcher;
146 import java.util.regex.Pattern;
147
148 import javax.annotation.Nullable;
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172 @Beta
173 public final class ArbitraryInstances {
174
175 private static final Ordering<Field> BY_FIELD_NAME = new Ordering<Field>() {
176 @Override public int compare(Field left, Field right) {
177 return left.getName().compareTo(right.getName());
178 }
179 };
180
181
182
183
184
185
186 private static MatchResult newMatchResult() {
187 Matcher matcher = Pattern.compile(".").matcher("X");
188 matcher.find();
189 return matcher.toMatchResult();
190 }
191
192 private static final ClassToInstanceMap<Object> DEFAULTS = ImmutableClassToInstanceMap.builder()
193
194 .put(Object.class, "")
195 .put(Number.class, 0)
196 .put(UnsignedInteger.class, UnsignedInteger.ZERO)
197 .put(UnsignedLong.class, UnsignedLong.ZERO)
198 .put(BigInteger.class, BigInteger.ZERO)
199 .put(BigDecimal.class, BigDecimal.ZERO)
200 .put(CharSequence.class, "")
201 .put(String.class, "")
202 .put(Pattern.class, Pattern.compile(""))
203 .put(MatchResult.class, newMatchResult())
204 .put(TimeUnit.class, TimeUnit.SECONDS)
205 .put(Charset.class, Charsets.UTF_8)
206 .put(Currency.class, Currency.getInstance(Locale.US))
207 .put(Locale.class, Locale.US)
208
209 .put(CharMatcher.class, CharMatcher.NONE)
210 .put(Joiner.class, Joiner.on(','))
211 .put(Splitter.class, Splitter.on(','))
212 .put(Optional.class, Optional.absent())
213 .put(Predicate.class, Predicates.alwaysTrue())
214 .put(Equivalence.class, Equivalence.equals())
215 .put(Ticker.class, Ticker.systemTicker())
216 .put(Stopwatch.class, Stopwatch.createUnstarted())
217
218 .put(InputStream.class, new ByteArrayInputStream(new byte[0]))
219 .put(ByteArrayInputStream.class, new ByteArrayInputStream(new byte[0]))
220 .put(Readable.class, new StringReader(""))
221 .put(Reader.class, new StringReader(""))
222 .put(StringReader.class, new StringReader(""))
223 .put(Buffer.class, ByteBuffer.allocate(0))
224 .put(CharBuffer.class, CharBuffer.allocate(0))
225 .put(ByteBuffer.class, ByteBuffer.allocate(0))
226 .put(ShortBuffer.class, ShortBuffer.allocate(0))
227 .put(IntBuffer.class, IntBuffer.allocate(0))
228 .put(LongBuffer.class, LongBuffer.allocate(0))
229 .put(FloatBuffer.class, FloatBuffer.allocate(0))
230 .put(DoubleBuffer.class, DoubleBuffer.allocate(0))
231 .put(File.class, new File(""))
232 .put(ByteSource.class, ByteSource.empty())
233 .put(CharSource.class, CharSource.empty())
234 .put(ByteSink.class, NullByteSink.INSTANCE)
235 .put(CharSink.class, NullByteSink.INSTANCE.asCharSink(Charsets.UTF_8))
236
237 .put(Iterator.class, ImmutableSet.of().iterator())
238 .put(PeekingIterator.class, Iterators.peekingIterator(Iterators.emptyIterator()))
239 .put(ListIterator.class, ImmutableList.of().listIterator())
240 .put(Iterable.class, ImmutableSet.of())
241 .put(Collection.class, ImmutableList.of())
242 .put(ImmutableCollection.class, ImmutableList.of())
243 .put(List.class, ImmutableList.of())
244 .put(ImmutableList.class, ImmutableList.of())
245 .put(Set.class, ImmutableSet.of())
246 .put(ImmutableSet.class, ImmutableSet.of())
247 .put(SortedSet.class, ImmutableSortedSet.of())
248 .put(ImmutableSortedSet.class, ImmutableSortedSet.of())
249 .put(NavigableSet.class, Sets.unmodifiableNavigableSet(Sets.newTreeSet()))
250 .put(Map.class, ImmutableMap.of())
251 .put(ImmutableMap.class, ImmutableMap.of())
252 .put(SortedMap.class, ImmutableSortedMap.of())
253 .put(ImmutableSortedMap.class, ImmutableSortedMap.of())
254 .put(NavigableMap.class, Maps.unmodifiableNavigableMap(Maps.newTreeMap()))
255 .put(Multimap.class, ImmutableMultimap.of())
256 .put(ImmutableMultimap.class, ImmutableMultimap.of())
257 .put(ListMultimap.class, ImmutableListMultimap.of())
258 .put(ImmutableListMultimap.class, ImmutableListMultimap.of())
259 .put(SetMultimap.class, ImmutableSetMultimap.of())
260 .put(ImmutableSetMultimap.class, ImmutableSetMultimap.of())
261 .put(SortedSetMultimap.class, Multimaps.unmodifiableSortedSetMultimap(TreeMultimap.create()))
262 .put(Multiset.class, ImmutableMultiset.of())
263 .put(ImmutableMultiset.class, ImmutableMultiset.of())
264 .put(SortedMultiset.class, ImmutableSortedMultiset.of())
265 .put(ImmutableSortedMultiset.class, ImmutableSortedMultiset.of())
266 .put(BiMap.class, ImmutableBiMap.of())
267 .put(ImmutableBiMap.class, ImmutableBiMap.of())
268 .put(Table.class, ImmutableTable.of())
269 .put(ImmutableTable.class, ImmutableTable.of())
270 .put(RowSortedTable.class, Tables.unmodifiableRowSortedTable(TreeBasedTable.create()))
271 .put(ClassToInstanceMap.class, ImmutableClassToInstanceMap.builder().build())
272 .put(ImmutableClassToInstanceMap.class, ImmutableClassToInstanceMap.builder().build())
273 .put(Comparable.class, ByToString.INSTANCE)
274 .put(Comparator.class, AlwaysEqual.INSTANCE)
275 .put(Ordering.class, AlwaysEqual.INSTANCE)
276 .put(Range.class, Range.all())
277 .put(MapConstraint.class, MapConstraints.notNull())
278 .put(MapDifference.class, Maps.difference(ImmutableMap.of(), ImmutableMap.of()))
279 .put(SortedMapDifference.class,
280 Maps.difference(ImmutableSortedMap.of(), ImmutableSortedMap.of()))
281
282 .put(AnnotatedElement.class, Object.class)
283 .put(GenericDeclaration.class, Object.class)
284 .put(Type.class, Object.class)
285 .build();
286
287
288
289
290
291 private static final ConcurrentMap<Class<?>, Class<?>> implementations = Maps.newConcurrentMap();
292
293 private static <T> void setImplementation(Class<T> type, Class<? extends T> implementation) {
294 checkArgument(type != implementation, "Don't register %s to itself!", type);
295 checkArgument(!DEFAULTS.containsKey(type),
296 "A default value was already registered for %s", type);
297 checkArgument(implementations.put(type, implementation) == null,
298 "Implementation for %s was already registered", type);
299 }
300
301 static {
302 setImplementation(Appendable.class, StringBuilder.class);
303 setImplementation(BlockingQueue.class, LinkedBlockingDeque.class);
304 setImplementation(BlockingDeque.class, LinkedBlockingDeque.class);
305 setImplementation(ConcurrentMap.class, ConcurrentHashMap.class);
306 setImplementation(ConcurrentNavigableMap.class, ConcurrentSkipListMap.class);
307 setImplementation(CountDownLatch.class, Dummies.DummyCountDownLatch.class);
308 setImplementation(Deque.class, ArrayDeque.class);
309 setImplementation(OutputStream.class, ByteArrayOutputStream.class);
310 setImplementation(PrintStream.class, Dummies.InMemoryPrintStream.class);
311 setImplementation(PrintWriter.class, Dummies.InMemoryPrintWriter.class);
312 setImplementation(Queue.class, ArrayDeque.class);
313 setImplementation(Random.class, Dummies.DeterministicRandom.class);
314 setImplementation(ScheduledThreadPoolExecutor.class,
315 Dummies.DummyScheduledThreadPoolExecutor.class);
316 setImplementation(ThreadPoolExecutor.class, Dummies.DummyScheduledThreadPoolExecutor.class);
317 setImplementation(Writer.class, StringWriter.class);
318 setImplementation(Runnable.class, Dummies.DummyRunnable.class);
319 setImplementation(ThreadFactory.class, Dummies.DummyThreadFactory.class);
320 setImplementation(Executor.class, Dummies.DummyExecutor.class);
321 }
322
323 @SuppressWarnings("unchecked")
324 @Nullable
325 private static <T> Class<? extends T> getImplementation(Class<T> type) {
326 return (Class<? extends T>) implementations.get(type);
327 }
328
329 private static final Logger logger = Logger.getLogger(ArbitraryInstances.class.getName());
330
331
332
333
334
335 @Nullable public static <T> T get(Class<T> type) {
336 T defaultValue = DEFAULTS.getInstance(type);
337 if (defaultValue != null) {
338 return defaultValue;
339 }
340 Class<? extends T> implementation = getImplementation(type);
341 if (implementation != null) {
342 return get(implementation);
343 }
344 if (type.isEnum()) {
345 T[] enumConstants = type.getEnumConstants();
346 return (enumConstants.length == 0)
347 ? null
348 : enumConstants[0];
349 }
350 if (type.isArray()) {
351 return createEmptyArray(type);
352 }
353 T jvmDefault = Defaults.defaultValue(Primitives.unwrap(type));
354 if (jvmDefault != null) {
355 return jvmDefault;
356 }
357 if (Modifier.isAbstract(type.getModifiers()) || !Modifier.isPublic(type.getModifiers())) {
358 return arbitraryConstantInstanceOrNull(type);
359 }
360 final Constructor<T> constructor;
361 try {
362 constructor = type.getConstructor();
363 } catch (NoSuchMethodException e) {
364 return arbitraryConstantInstanceOrNull(type);
365 }
366 constructor.setAccessible(true);
367 try {
368 return constructor.newInstance();
369 } catch (InstantiationException impossible) {
370 throw new AssertionError(impossible);
371 } catch (IllegalAccessException impossible) {
372 throw new AssertionError(impossible);
373 } catch (InvocationTargetException e) {
374 logger.log(Level.WARNING, "Exception while invoking default constructor.", e.getCause());
375 return arbitraryConstantInstanceOrNull(type);
376 }
377 }
378
379 @Nullable private static <T> T arbitraryConstantInstanceOrNull(Class<T> type) {
380 Field[] fields = type.getDeclaredFields();
381 Arrays.sort(fields, BY_FIELD_NAME);
382 for (Field field : fields) {
383 if (Modifier.isPublic(field.getModifiers())
384 && Modifier.isStatic(field.getModifiers())
385 && Modifier.isFinal(field.getModifiers())) {
386 if (field.getGenericType() == field.getType()
387 && type.isAssignableFrom(field.getType())) {
388 field.setAccessible(true);
389 try {
390 T constant = type.cast(field.get(null));
391 if (constant != null) {
392 return constant;
393 }
394 } catch (IllegalAccessException impossible) {
395 throw new AssertionError(impossible);
396 }
397 }
398 }
399 }
400 return null;
401 }
402
403 private static <T> T createEmptyArray(Class<T> arrayType) {
404 return arrayType.cast(Array.newInstance(arrayType.getComponentType(), 0));
405 }
406
407
408 private static final class Dummies {
409
410 public static final class InMemoryPrintStream extends PrintStream {
411 public InMemoryPrintStream() {
412 super(new ByteArrayOutputStream());
413 }
414 }
415
416 public static final class InMemoryPrintWriter extends PrintWriter {
417 public InMemoryPrintWriter() {
418 super(new StringWriter());
419 }
420 }
421
422 public static final class DeterministicRandom extends Random {
423 @SuppressWarnings("unused")
424 public DeterministicRandom() {
425 super(0);
426 }
427 }
428
429 public static final class DummyScheduledThreadPoolExecutor extends ScheduledThreadPoolExecutor {
430 public DummyScheduledThreadPoolExecutor() {
431 super(1);
432 }
433 }
434
435 public static final class DummyCountDownLatch extends CountDownLatch {
436 public DummyCountDownLatch() {
437 super(0);
438 }
439 }
440
441 public static final class DummyRunnable implements Runnable, Serializable {
442 @Override public void run() {}
443 }
444
445 public static final class DummyThreadFactory implements ThreadFactory, Serializable {
446 @Override public Thread newThread(Runnable r) {
447 return new Thread(r);
448 }
449 }
450
451 public static final class DummyExecutor implements Executor, Serializable {
452 @Override public void execute(Runnable command) {}
453 }
454 }
455
456 private static final class NullByteSink extends ByteSink implements Serializable {
457 private static final NullByteSink INSTANCE = new NullByteSink();
458
459 @Override public OutputStream openStream() {
460 return ByteStreams.nullOutputStream();
461 }
462 }
463
464
465
466
467 private static final class ByToString implements Comparable<Object>, Serializable {
468 private static final ByToString INSTANCE = new ByToString();
469
470 @Override public int compareTo(Object o) {
471 return toString().compareTo(o.toString());
472 }
473
474 @Override public String toString() {
475 return "BY_TO_STRING";
476 }
477
478 private Object readResolve() {
479 return INSTANCE;
480 }
481 }
482
483
484 private static final class AlwaysEqual extends Ordering<Object> implements Serializable {
485 private static final AlwaysEqual INSTANCE = new AlwaysEqual();
486
487 @Override public int compare(Object o1, Object o2) {
488 return 0;
489 }
490
491 @Override public String toString() {
492 return "ALWAYS_EQUAL";
493 }
494
495 private Object readResolve() {
496 return INSTANCE;
497 }
498 }
499
500 private ArbitraryInstances() {}
501 }